package com.koc.robot;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;

import com.koc.robot.common.Vector;

import android.opengl.GLES11;
import android.view.MotionEvent;

public class MenuState extends BasicState
{
	// static for easy access by child controls
	public static int menuoffset;
	public static int menuoffsett;
	public static int menuoffsetx;
	public static int menuoffsetxt;
	
	private ArrayList<MenuButton> menubuttons;
	private ArrayList<LevelButton> levelbuttons;
	
	public int currentpage;
	public int pages;
	
	private float drawcenterX;
	private float drawcenterY;
	private Map menumap;
	private Scene scene;
	
	public MenuState(int x, int y)
	{
		menuoffset = y;
		menuoffsett = y;
		menuoffsetx = x;
		menuoffsetxt = x;
		
		Global.fadetimer = 0.0f;
		Global.fadecolor = 0.0f;
		Global.fadetimert = 1.0f;
		
		scene = new Scene();
		menumap = new Map(scene);
	
		mStateTag = State.STATE_MENU;
	}
	
	@Override
	public void load()
	{
		loadlevels();
		
		Global.musicvolume = 0;
		Global.musicplayer.playBackgroundMusic("sounds/menu_back.ogg", true);
		Global.musicplayer.setBackgroundVolume(Global.musicvolume);
		
		// framerate is too low, remove some blocks to draw
		int blockNum = 120;
		
		Global.backgroundblocks = new BackgroundBlock[blockNum]; 
		
		for (int i = 0; i < blockNum; i++)
		{
			Global.backgroundblocks[i] = new BackgroundBlock();
			Global.backgroundblocks[i].resetbox(true);
		}
		
		// init global block buffers
		Global.blockVertexArrays = new int[blockNum * 4 * 3];
		ByteBuffer vfb0 = ByteBuffer.allocateDirect(blockNum * 4 * 3 * 4);
		vfb0.order(ByteOrder.nativeOrder());
		Global.blockVertexBuffer = vfb0.asFloatBuffer();
		
		ByteBuffer idxb0 = ByteBuffer.allocateDirect(blockNum * 6 * 2);
		idxb0.order(ByteOrder.nativeOrder());
		Global.blockIndexBuffer = idxb0.asShortBuffer();
		
		// fill in the index buffer
		for (int i = 0; i < blockNum; i++)
		{
			Global.blockIndexBuffer.put((short) (i * 4 + 0));
			Global.blockIndexBuffer.put((short) (i * 4 + 1));
			Global.blockIndexBuffer.put((short) (i * 4 + 2));
			Global.blockIndexBuffer.put((short) (i * 4 + 0));
			Global.blockIndexBuffer.put((short) (i * 4 + 2));
			Global.blockIndexBuffer.put((short) (i * 4 + 3));
		}
		Global.blockIndexBuffer.position(0);
		
		int bufferIDs[] = new int[2];
		GLES11.glGenBuffers(2, bufferIDs, 0);
		Global.blockVertexBufferID = bufferIDs[0];
		Global.blockIndexBufferID = bufferIDs[1];
		
		GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, Global.blockVertexBufferID);
		GLES11.glBufferData(GLES11.GL_ARRAY_BUFFER, Global.blockVertexBuffer.capacity() * 4,
				Global.blockVertexBuffer, GLES11.GL_DYNAMIC_DRAW);
		GLES11.glBindBuffer(GLES11.GL_ELEMENT_ARRAY_BUFFER, Global.blockIndexBufferID);
		GLES11.glBufferData(GLES11.GL_ELEMENT_ARRAY_BUFFER, Global.blockIndexBuffer.capacity() * 2,
				Global.blockIndexBuffer, GLES11.GL_STATIC_DRAW);
		
		// init menu map
		menumap.load("menu");
		scene.setRotateCenter(menumap.getMapWidth() / 2 + 0.5f, menumap.getMapHeight() / 2,
				menumap.getMapDepth() / 2 + 0.5f);
		scene.setDrawCenter(new Vector(Global.screenwidth / 2.0f, 140.0f));
		scene.setBlockWidth(45.0f);
		scene.setPitch(0.0f);
		scene.setRotation(Common.PI_025);
		scene.setMap(menumap);
	
		// init menubuttons
		menubuttons = new ArrayList<MenuButton>();
		menubuttons.add(new MenuButton(Global.screenwidth / 2, 300, "Play levels"));
		menubuttons.get(menubuttons.size() - 1).setButtonDelegate(
				new ButtonDelegate()
				{
					@Override
					public void func()
					{
						Global.soundplayer.playEffect("sounds/proceed.ogg", false);
						menuoffsett = 500;
						menuoffsetxt = 0;
					}
				}
				);
		
		menubuttons.add(new MenuButton(Global.screenwidth / 2, 400, "Help"));
		menubuttons.add(new MenuButton(Global.screenwidth / 2, 500, "Credits"));
		menubuttons.add(new MenuButton(Global.screenwidth / 2, 600, "Exit"));
		menubuttons.add(new MenuButton(Global.screenwidth / 2, -45, "Back"));
		menubuttons.add(new MenuButton(Global.screenwidth / 2 - 100, 1100, "Yes"));
		menubuttons.add(new MenuButton(Global.screenwidth / 2 + 100, 1100, "No"));
		menubuttons.add(new MenuButton(Global.screenwidth / 2 + Global.screenwidth, 650, "< Okay I get it"));
		menubuttons.add(new MenuButton(-Global.screenwidth / 2, 650, "Let's do this >"));
		menubuttons.add(new MenuButton(Global.screenwidth - 141, -45, "Next >"));
		menubuttons.add(new MenuButton(198, -45, "< Previous"));
		menubuttons.add(new MenuButton(Global.screenwidth / 2 + Global.screenwidth, 0, "< Awesome"));
		
		currentpage = (int) Math.min(((Global.currentmap  - 1) / 16.0f), Global.leveldatas.size() / 16.0f);
		pages = (int) (Global.leveldatas.size() / 17.0f);
		
		menubuttons.get(10).setActive(true);
		menubuttons.get(9).setActive(true);
		if (currentpage == 0)
		{
			menubuttons.get(10).setActive(false);
		}
		
		if (currentpage == pages)
		{
			menubuttons.get(9).setActive(false);
		}
		
		levelbuttons = new ArrayList<LevelButton>();
		for (int i = 0; i < Global.leveldatas.size(); i++)
		{
			if (i >= currentpage * 16 && i < Math.min((currentpage + 1) * 16, Global.leveldatas.size()))
			{
				int j = i % 16;
				float x = Math.round((j % 4) * 247.5 + 125);
				float y = ((int)((j + 4) / 4)) * 100 - 570;
				LevelButton button;
				if (i < Global.unlockedlevels)
				{
					button = new LevelButton(x, y, Global.leveldatas.get(i).name, i, true);
				}
				else
				{
					button = new LevelButton(x, y, Global.leveldatas.get(i).name, i, false);
				}
				levelbuttons.add(button);
			}
		}
	}
	
	@Override
	public void update(float dt)
	{
		if (Global.fadetimer != Global.fadetimert)
		{
			if (Global.fadetimert > Global.fadetimer)
			{
				Global.fadetimer = Global.fadetimer + dt;
				if (Global.fadetimer >= Global.fadetimert)
				{
					Global.fadetimer = Global.fadetimert;
					Global.fadecolor = Global.fadetimer;
					Global.musicplayer.setBackgroundVolume(1.0f);
				}
				else
				{
					Global.musicplayer.setBackgroundVolume(Global.fadetimer);
					Global.fadecolor = Global.fadetimer;
				}
			}
			else
			{
				Global.fadetimer = Global.fadetimer - dt;
				if (Global.fadetimer <= Global.fadetimert)
				{
					Global.fadetimer = Global.fadetimert;
					Global.fadecolor = Global.fadetimer;
					Global.musicplayer.stopBackgroundMusic();
					// TODO: fadegoal logic
				}
				else
				{
					if (menuoffsett < 0)
					{
						Global.musicplayer.setBackgroundVolume(Global.fadetimer * 0.3f);
					}
					else
					{
						Global.musicplayer.setBackgroundVolume(Global.fadetimer);
					}
					Global.fadecolor = Global.fadetimer;
				}
			}
		}
		else
		{
			if (menuoffsett >= 0)
			{
				float currentMusicVolume = Global.musicplayer.getBackgroundVolume();
				currentMusicVolume += dt;
				if (currentMusicVolume > 1.0f)
				{
					currentMusicVolume = 1.0f;
				}
				Global.musicplayer.setBackgroundVolume(currentMusicVolume);
			}
		}
		
		if (menuoffsett < 0 && Global.fadetimert != 0)
		{
			float currentMusicVolume = Global.musicplayer.getBackgroundVolume();
			currentMusicVolume -= 0.3f;
			if (currentMusicVolume < 0.3f)
			{
				currentMusicVolume = 0.3f;
			}
			Global.musicplayer.setBackgroundVolume(currentMusicVolume);
		}
		
		// get closest full rot
		float rot = scene.getRotation() + Common.PI_025;
		while (rot > Common.PI_025)
		{
			rot = rot - Common.PI_05;
		}
		
		float speed = Math.abs(rot) * 2 + 0.005f;
		
		float currot = scene.getRotation();
		
		currot = currot + speed * dt;
		
		while (currot > Common.PI_2)
		{
			currot = currot - Common.PI_2;
		}
		while (currot < 0)
		{
			currot = currot + Common.PI_2;
		}
		scene.setRotation(currot);
		
		if (menuoffset != menuoffsett)
		{
			if (menuoffset < menuoffsett)
			{
				menuoffset = (int) (menuoffset + (menuoffsett - menuoffset) * 4 * dt + 2 * dt);
				if (menuoffset > menuoffsett)
				{
					menuoffset = menuoffsett;
				}
			}
			else 
			{
				menuoffset = (int)(menuoffset + (menuoffsett - menuoffset) * 4 * dt - 2 * dt);
				if (menuoffset < menuoffsett)
				{
					menuoffset = menuoffsett;
				}
			}
		}
		
		if (menuoffsetx != menuoffsetxt)
		{
			if (menuoffsetx < menuoffsetxt)
			{
				menuoffsetx = (int)(menuoffsetx + (menuoffsetxt - menuoffsetx) * 4 * dt + 2 * dt);
				if (menuoffsetx > menuoffsetxt)
				{
					menuoffsetx = menuoffsetxt;
				}
			}
			else
			{
				menuoffsetx = (int)(menuoffsetx + (menuoffsetxt - menuoffsetx) * 4 * dt - 2 * dt);
				if (menuoffsetx < menuoffsetxt)
				{
					menuoffsetx = menuoffsetxt;
				}
			} 
		}
	}
	
	@Override
	public void onTouched(MotionEvent e)
	{
		float touchX = e.getX();
		float touchY = e.getY();
		touchX = touchX / Global.devicewidth * Global.screenwidth;
		touchY = touchY / Global.deviceheight * Global.screenheight;
		touchY = touchY - this.menuoffset;
		touchX = touchX - this.menuoffsetx;
		
		for (int i = 0; i < menubuttons.size(); i++)
		{
			menubuttons.get(i).mousepressed(touchX, touchY);
		}
	}
	
	
	@Override
	public void render()
	{
		GLES11.glTranslatef(menuoffsetx, menuoffset, 0);
		
		GraphicsHelper.setColor(100.0f / 255.0f, 100.0f / 255.0f, 100.0f / 255.0f, 100.0f / 255.0f);
		GraphicsHelper.rectangle(DrawMode.DRAW_FILL, 30, 30, 964, 230);
		
		scene.render();
		
		GraphicsHelper.setFont(Global.menufont);
		
		if (menuoffset < 500 && menuoffset > -650)
		{
			menubuttons.get(0).render();
			menubuttons.get(1).render();
			menubuttons.get(2).render();
			menubuttons.get(3).render();
		}
		
		if (menuoffset > 0)
		{
			if (menuoffsetx < Global.screenwidth)
			{
				GraphicsHelper.setFont(Global.levelselectfont);
				for (int i = 0; i < levelbuttons.size(); i++)
				{
					LevelButton button = levelbuttons.get(i);
					button.render();
				}
				GraphicsHelper.setFont(Global.menufont);
				menubuttons.get(4).render();
				if (currentpage != pages)
				{
					menubuttons.get(9).render();
				}
				if (currentpage != 0)
				{
					menubuttons.get(10).render();
				}
			}
		}
		
		GLES11.glTranslatef(-menuoffsetx, -menuoffset, 0);
		
		GraphicsHelper.setColor(Global.fillcolor.R, Global.fillcolor.G, Global.fillcolor.B, 1.0f); 
		GraphicsHelper.draw(Global.scanlineimg, 0, (Global.creditss * 3.0f) % 5 - 5);
	}
	
	public void loadlevels() 
	{
		String[] mappaths = null;
		try
		{
			mappaths = Global.context.getAssets().list("maps");
		}
		catch (IOException e)
		{
			return;
		}
		
		Global.leveldatas = new ArrayList<LevelData>();
		
		for (int i = 0; i < mappaths.length; i++)
		{
			String path = mappaths[i];
			
			if(path.equals("menu.txt") || !path.endsWith(".txt"))
			{
				continue;
			} 
			
			LevelData leveldata = new LevelData();
			
			try
			{
				InputStream leveldatastream =  Global.context.getAssets().open("maps/" + path);
				BufferedReader br = new BufferedReader(new InputStreamReader(leveldatastream, "UTF-8"));
				
				ArrayList<String> txtcontents = new ArrayList<String>();
				
				String read = br.readLine();
				while (read != null)
				{
					txtcontents.add(read);
					read = br.readLine();
				}
				
				for (int j = 0; j < txtcontents.size(); j++)
				{
					String content = txtcontents.get(j);
					String[] s2 = content.split("=");
					if (s2[0].equals("name"))
						leveldata.name = s2[1];
					else if (s2[0].equals("text"))
						leveldata.text = s2[1];
					else if (s2[0].equals("time"))
						leveldata.goaltime = Float.parseFloat(s2[1]);
					else if (s2[0].equals("steps"))
						leveldata.goalsteps = Float.parseFloat(s2[1]);
					else if (s2[0].equals("warps"))
						leveldata.goalwarps = Float.parseFloat(s2[1]);
					else if (s2[0].equals("coins"))
						leveldata.coins = Integer.parseInt(s2[1]);
				}
				
				Global.leveldatas.add(leveldata);
			}
			catch (Exception ex)
			{
				return;
			}
			
			LevelData data = new LevelData();
			data.coins = 0;
		}
	}
}
